/**
 * 实现 中间件.路由.控制器的自动装载
 * 自动装载路由的注解
 * "auto_router" 表面这是一个路由文件
 * 实现页面级中间件
 * "midd("中间件名称:参数,参数")"
 * 自动装载中间件
 * “auto_midd("中间件名称")”
 * 自动装载控制器
 * "controller" 表明这是一个控制器
 * "prefix("页面级前缀(不推荐)")"
 * 写在方法外面就是页面级中间件，写在方法中就是接口级中间件
 * "midd(中间件名称:参数")
 * 路径必须写在方法中
 * "get('/yes')" get接口
 * "post('/yes')"post接口
 * 
 */
const sugar = gem('sugar');
const fs =require('fs');
module.exports=()=>{
    if(!gem_config.features.annotations)return;
    //获取自动装载所控制的空间
    Object.keys(global.gem_config.load_addresss).forEach(path=>{
        //遍历文件夹
        traverse(sugar.path(global.gem_config.load_addresss[path]));
    })
}

function traverse(path,arr=[]){
    // 时刻对比,无限循环,1秒钟循环一次
    setInterval(()=>{
        fs.readdirSync(path).map(e=>{
            if(!arr.includes(e)){
                arr.push(e);
                if(!fs.lstatSync(path+e).isDirectory()){
                    //新增加的文件，对其进行监控
                    try{
                        monitorFile(path+e,arr,e);
                    }catch (e){}
                }else{
                    //这是一个文件夹，调用自己
                    traverse(path+e+"\\");
                }
            }
        })
    },1000)
}

//监控文件
function monitorFile(path,arr,name){
    try{
    //判断是不是node文件
    if(path.endsWith(".js")){
        //进行一次解析
        load(path);
        //进行监控
        fs.watchFile((path),{
            interval:100,persistent:false
        },(cur, prv) => {
            if(fs.existsSync(path)){
                // console.log("重新加载注解")
                load(path)
            }else{
                //关闭自身的监控
                fs.unwatchFile(path);
                //踢出文件夹
                arr.splice(arr.indexOf(name),1);
                console.log("文件已删除:",path);
                //删除一下
                delete global.runRoute[path];
                delete global.runRouter[path]
                //合成一下
                loader("run_route").mergeRout();
            }
        })
    }
    }catch (Error){}
}



//进行加载
function load(path,type){
    try{
        //加载文件
        let fun = loader(path);
        //判断类型
        if(typeof fun === 'function' && /^class\s/.test(Function.prototype.toString.call(fun))){
            //这是一个类
            type = "class";
        }else if(['function','object'].includes(typeof fun)){
            type = typeof fun;
        }else{
            console.log(typeof fun)
            console.log("未知类型",path)
            return;
        }

        let annot = Object.keys(global.gem_config.annotation);
        let data = ({
                    "class":gem('load_class'),
                    "function":gem('load_method'),
                    "object":gem('load_object')
                    })[type](path,annot || [])

        //开始运行注解
        data.forEach(e=>{
            loader(global.gem_config.annotation[e.annotation])(path,e.name,...e.parameter)
        })
    }catch (err){console.log(err)}
}